home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
EXPR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
57KB
|
1,905 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
#define GEN
#include "hdr.h"
#include "vars.h"
#include "segment.h"
#include "gvars.h"
#include "attr.h"
#include "ops.h"
#include "type.h"
#include "namp.h"
#include "segmentp.h"
#include "genp.h"
#include "miscp.h"
#include "maincasp.h"
#include "setp.h"
#include "typep.h"
#include "gutilp.h"
#include "arithp.h"
#include "gmiscp.h"
#include "smiscp.h"
#include "chapp.h"
#include "axqrp.h"
#include "exprp.h"
static int rat_convert(Const, int *);
void gen_attribute(Node);
static int float_mantissa(int);
static void gen_type_attr(Symbol, int);
static int code_map(Symbol);
static int code_map_defined; /* set to FALSE if SETL version yields OM */
void gen_value(Node node) /*;gen_value*/
{
/*
* This procedure generates code for the v_expressions
* or, in other words, the right-hand-sides.
*
* - node is the tree expression for which code is to be generated.
*/
int save_tasks_declared, can_convert, rat_int;
Node pre_node, rec_type_node, id_node, static_node, init_node, obj_node,
exception_node, expr_node, init_call_node, task_node, entry_node,
index_node, value_node, arr_l_bd, arr_h_bd, val_l_bd, val_h_bd;
Symbol type_name, node_name, rec_type_name, proc_name, return_type,
obj_name, obj_type, model_name, exception_name, from_type, to_type,
accessed_type, discr_name;
Fortup ft1;
Symbol junk_var, comp_name, indx_type, value_type, indx_value_type;
Tuple stmts_list;
Node list_node, stmt_node, lhs, comp_node, type_node;
Tuple d_l, tup, indx_types;
Const value;
int i, stmts_list_i, size, ivalue;
long exprv; /* fixed point value */
#ifdef TRACE
if (debug_flag) {
gen_trace_node("GEN_VALUE", node);
}
#endif
while (N_KIND(node) == as_insert) {
FORTUP(pre_node = (Node), N_LIST(node), ft1);
compile(pre_node);
ENDFORTUP(ft1);
node = N_AST1(node);
}
type_name = get_type(node);
if (N_KIND(node) == as_null)
gen_s(I_PUSH_EFFECTIVE_ADDRESS, symbol_null);
else if (is_simple_name(node)) {
node_name = N_UNQ(node);
if (is_renaming(node_name)) {
gen_ks(I_PUSH, mu_addr, node_name);
if (is_array_type(type_name)) {
/* Note: can't be a renaming of a formal parm (transformed */
/* to normal variable). */
gen_s(I_PUSH_EFFECTIVE_ADDRESS, type_name);
}
optional_deref(type_name);
}
else if (is_simple_type(type_name)) {
gen_ks(I_PUSH, kind_of(type_name), node_name);
}
else {
gen_s(I_PUSH_EFFECTIVE_ADDRESS, node_name);
/* Arrays are treated in a different manner, depending on their */
/* nature: parameters, constants, variables... */
if (is_array_type(type_name)) {
if (is_formal_parameter(node_name)) {
/* For a parm, the type template follows the parameter */
/* in the stack */
gen_s(I_PUSH_EFFECTIVE_ADDRESS,
assoc_symbol_get(node_name, FORMAL_TEMPLATE));
}
else {
/* otherwise, the type template address is pushed on the */
/* stack */
gen_s(I_PUSH_EFFECTIVE_ADDRESS, type_name);
}
}
}
}
else {
switch (N_KIND(node) ) {
case(as_create_task):
gen_s(I_CREATE_TASK, type_name);
break;
case(as_discard):
expr_node = N_AST1(node);
junk_var = new_unique_name("junk"); /* TBSL: Reusing same var */
next_local_reference(junk_var);
gen_ks(I_DECLARE, kind_of(N_TYPE(node)), junk_var);
gen_value(expr_node);
gen_ksc(I_POP, kind_of(N_TYPE(node)), junk_var,
"Used only for check");
break;
case(as_ivalue):
case(as_real_literal):
case(as_int_literal):
if (is_fixed_type(type_name)) {
exprv = rat_tof(get_ivalue(node),
small_of(base_type(type_name)), size_of(type_name));
/* the evaluation may have raised the overflow flag. Therefore,
* constraint_error has to be raised at execution time
*/
if ( ! arith_overflow) {
gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name),
fixed_const(exprv));
}
else {
gen_s(I_LOAD_EXCEPTION_REGISTER, symbol_constraint_error);
gen(I_RAISE);
}
}
else if (is_simple_type(type_name)) {
value = get_ivalue(node);
if (is_float_type(type_name)) {
/* gen_(I_PUSH_IMMEDIATE, kind_of(type_name), value,
* ' = '+str(I_TO_F(value)));
*/
if (is_const_rat(value)) { /* try to cnvrt rtnl to real*/
chaos("expr.c: rational seen when real expected");
}
gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name), value);
}
else {
if (is_const_rat(value)) { /* try to cnvrt rtnl to int */
rat_int = rat_convert(value, &can_convert);
if (can_convert) {
gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name),
int_const(rat_int));
}
else {
gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name), value);
}
}
else if (is_const_uint(value)) {
/* try to convert universal integer to integer */
ivalue = int_toi(UINTV(value));
if (!arith_overflow) {/* if can convert to integer */
gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name),
int_const(ivalue));
}
else { /* just try again as universal integer */
gen_s(I_LOAD_EXCEPTION_REGISTER,
symbol_constraint_error);
gen(I_RAISE);
/* the exceptn has to be raised (overflow on int)
* gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name),
* value);
*/
}
}
else {
gen_kv(I_PUSH_IMMEDIATE, kind_of(type_name), value);
}
}
}
else
compiler_error("structured ivalue");
break;
case(as_string_ivalue):
/* This created a segment containing the string literal... */
/* TBSL: note that array_ivalue returns a Segment */
obj_name = get_constant_name(array_ivalue(node));
type_name = N_TYPE(node);
gen_s(I_PUSH_EFFECTIVE_ADDRESS, obj_name);
gen_s(I_PUSH_EFFECTIVE_ADDRESS, type_name);
break;
case(as_index):
gen_subscript(node);
optional_deref(type_name);
break;
case(as_selector):
gen_address(node);
optional_deref(type_name);
break;
case(as_discr_ref):
discr_name = N_UNQ(node);
rec_type_node = N_AST1(node);
rec_type_name = N_UNQ(rec_type_node);
gen_sc(I_PUSH_EFFECTIVE_ADDRESS, rec_type_name,
"fetch discriminant from template");
/* SETL version has discr_name as last argument, this is presumably
* comment part of instruction. For now ignore this
* gen_ki(I_ADD_IMMEDIATE, mu_word,
* TT_C_RECORD_DISCR + FIELD_OFFSET(discr_name)(TARGET),
* discr_name);
*/
/* TBSL: review trnsltn of next line VERY carefully ds 10-2-85 */
if (TYPE_KIND(rec_type_name) == TT_D_RECORD) {
gen_ki(I_ADD_IMMEDIATE, mu_word,
((sizeof(struct tt_d_type)/sizeof(int)) +
1 + 2 * FIELD_OFFSET(discr_name)));
}
else {
gen_ki(I_ADD_IMMEDIATE, mu_word,
((sizeof(struct tt_d_type)/sizeof(int))
+ FIELD_OFFSET(discr_name)));
}
gen_k(I_DEREF, kind_of(type_name));
break;
case(as_all):
gen_address(node);
if (is_simple_type(type_name)) {
gen_k(I_DEREF, kind_of(type_name));
}
else {
Symbol not_null;
/* test for null explicitly, because optional_deref is a noop
* on an array or record (which are always references).
*/
gen_k(I_DUPLICATE, mu_addr);
gen_s(I_PUSH_EFFECTIVE_ADDRESS, symbol_null);
gen_k(I_COMPARE, mu_addr);
not_null = new_unique_name("ok_access");
gen_s(I_JUMP_IF_FALSE, not_null);
gen_s(I_LOAD_EXCEPTION_REGISTER, symbol_constraint_error);
gen(I_RAISE);
gen_s(I_LABEL, not_null);
}
break;
case(as_call):
id_node = N_AST1(node);
proc_name = N_UNQ(id_node);
return_type = TYPE_OF(proc_name);
gen_kc(I_DUPLICATE, kind_of(return_type), "place holder");
compile(node); /* processed from now as a procedure call */
break;
case(as_slice):
gen_address(node);
break;
case(as_raise):
compile(node);
break;
case(as_attribute):
case(as_range_attribute):
gen_attribute(node);
break;
case(as_record_aggregate):